package com.capybara.account.base;


import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 查询参数
 *
 * @param <T>
 * @author wangguochao
 */
@Data
@Slf4j
public class BaseParam<T> implements Serializable {
     /**
     * 驼峰模式
     */
    private static Pattern humpPattern = Pattern.compile("[A-Z]");
    /**
     * 实体ID
     */
    private String id;
    /**
     * 第几页
     */
    private int page;
    /**
     * 每页条数
     */
    private int size;
    /**
     * 排序方式
     */
    private String direction;
    /**
     * 排序字段
     */
    private String field;

    /**
     * 区间开始对象映射（需要开始属性与结束属性连续）
     */
    private Map<String, Object> betweenStartObjectMap = new HashMap<>(16);

    /**
     * 驼峰转下划线,效率比上面高
     */
    private static String humpToLine2(String str) {
        Matcher matcher = humpPattern.matcher(str);
        StringBuilder sb = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    /**
     * 分页尾
     */
    public int getMax() {
        return this.getMin() + getSize();
    }

    /**
     * 分页首
     */
    public int getMin() {
        return page * getSize();
    }

    /**
     * 获取大小
     *
     * @return int
     */
    public int getSize() {
        return size == 0 ? 20 : Math.min(1000, size);
    }



    /**
     * 联接查询
     *
     * @return {@link MPJLambdaWrapper}<{@link T}>
     */
    public MyLambdaWrapper<T> joinQuery(Class<T> clazz) {
        MyLambdaWrapper<T> wrapper = new MyLambdaWrapper<>(clazz,getPage(),getSize());
        joinUnsortedQuery(wrapper);
        return wrapper;
    }

    /**
     * 未排序查询
     *
     * @param wrapper 包装器
     */
    private void joinUnsortedQuery(MPJLambdaWrapper<T> wrapper) {
        Class<?> clazz = this.getClass();
        Field[] fields = clazz.getDeclaredFields();
        String alias = wrapper.getAlias();
        for (Field item : fields) {
            try {
                if (item.isAnnotationPresent(MyIgnore.class)) {
                    continue;
                }
                //打开私有访问
                item.setAccessible(true);
                //获取属性
                String name = item.getName();
                String line = alias != null ? alias + "." + humpToLine2(name) : humpToLine2(name);
                //获取属性值
                Object value = item.get(this);
                if (item.isAnnotationPresent(MyLike.class)) {
                    String valueStr = value instanceof String ? value.toString().trim() : "";
                    wrapper.likeIfExists(line, valueStr);
                } else if (item.isAnnotationPresent(MyEq.class)) {
                    wrapper.eqIfExists(line, value);
                } else if (item.isAnnotationPresent(MyNe.class)) {
                    wrapper.neIfExists(line, value);
                } else if (item.isAnnotationPresent(MyLe.class)) {
                    wrapper.leIfExists(line, value);
                } else if (item.isAnnotationPresent(MyGe.class)) {
                    wrapper.geIfExists(line, value);
                } else if (item.isAnnotationPresent(MyIn.class)) {
                    MyIn annotation = item.getAnnotation(MyIn.class);
                   if (value instanceof List list){
                       wrapper.in(humpToLine2(annotation.value()), list);
                   }
                } else if (item.isAnnotationPresent(MyBetween.class)) {
                    MyBetween annotation = item.getAnnotation(MyBetween.class);
                    if (value instanceof List list) {
                        wrapper.between(humpToLine2(annotation.value()), list.get(0), list.get(1));
                    } else {
                        betweenStartObjectMap.put(annotation.value(), value);
                    }
                }
            } catch (IllegalAccessException e) {
                log.error("请求参数转化错误");
            }
        }
    }

}
